iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
自我挑戰組

一鍵完成六套開源防禦系統整合系列 第 26 篇

Portainer:容器的管理畫面

  • 分享至 

  • xImage
  •  

防禦節點(主機 B)上除了 WAF,還裝了幾個別人寫的系統。「搭配元件篇」這一系列每篇只談一個,不深入它的設定細節,只回答三件事:它是什麼、它在主機 A 與主機 B 之間佔哪一段、少了它整體會缺什麼。本篇是 Portainer,也是本系列最後一篇。主機與位址沿用防禦節點那一套:主機 A(192.168.0.111)是 BeakPlatform,主機 B(192.168.0.112)是防禦節點。

先講結論。 Portainer 是 Docker 的網頁管理介面:主機 B 上的 12 個容器,在它裡面可以看狀態、看紀錄、重啟、進到容器裡下指令。它和防禦這件事完全無關,不在任何一條資料流上,主機 A 不知道它存在;它只是替「不想打 docker 指令的人」準備的畫面。它拿到的權限卻是整台主機裡最大的:它直接掛著 Docker 的控制通道,能登入 Portainer 的人等於主機 B 的 root。

另外有一段過程值得先知道:2026 年 10 月 9 日之前的安裝包內建 2.21.4,連不上 Ubuntu 24.04 目前的 Docker,登入後看得到容器的數量,點進去就是「環境無法連線」,而且出廠沒登記任何環境,要自己開一次精靈頁。現在的安裝包已換成 2.45.2,本機的 Docker 也由安裝腳本登記好。原因、證據與換版對已裝過的人的影響在第四節。

一、它是什麼

Portainer 是 Portainer.io 公司維護的容器管理介面,分社群版(Community Edition,授權 zlib)與商業版。本安裝包用的是社群版,容器映像 portainer/portainer-ce:2.45.2(2026 年 10 月發布的長期支援版),官方未修改的版本;2026 年 10 月 9 日之前的安裝包是 2.21.4,差別見第四節。它自己也是一個容器,透過 Docker 的 Unix socket(/var/run/docker.sock)跟主機上的 Docker 引擎講話,所以能看到、操作同一台主機上的所有容器,包括它自己。

它在本安裝包裡的樣子:

項目 內容
是否安裝 預設會裝。安裝時加 --no-ui 就不裝,Grafana 與 EveBox 也一起不裝
網址 https://192.168.0.112:9443/,HTTPS,憑證是它自己簽的,瀏覽器會出現安全警告,選「繼續前往」
誰能連 由主機 B 的防火牆限制來源:安裝時 --admin-ips 列出的位址與主機 A。其他來源連線逾時
帳號 admin 一個。密碼在安裝時隨機產生,印在安裝結尾,也存在主機 B 的 .env(PORTAINER_ADMIN_PASSWORD)
它管什麼 本機的 Docker,安裝腳本在它起來之後用它的 API 登記成一個名為 local 的「環境」。Portainer 出廠時什麼都不管,要開過精靈頁才會登記,安裝腳本替讀者做掉了這一步。見第三節
它自己的資料 帳號、設定、環境清單,存在它自己的一個小資料庫裡,放在名為 portainer-data 的資料卷。實測 256 KB
資源 實測一台節點閒置時約佔 20 MB 記憶體;映像檔 201 MB(舊版 2.21.4 是 398 MB)

密碼為什麼要在安裝時就設好,compose 檔裡有一段註解說明:Portainer 啟動後 5 分鐘內沒有人建立管理員,它會把自己鎖起來,而本節點安裝加下載映像檔不只 5 分鐘。所以安裝腳本先產生密碼、寫進一個檔案,Portainer 第一次啟動時讀這個檔案建帳號。這個檔案只在資料卷是空的那一次有效;之後改 .env 裡的密碼不會生效,要在畫面上改。

二、它接在哪裡

https://ithelp.ithome.com.tw/upload/images/20261010/20184261Ynjg9vZqa6.png
(圖01:Portainer 的位置。黑色實線是操作的方向,紅色點線是它掛著的 Docker 控制通道(這條線的意義見第五節),灰色實線是它自己的資料,灰色虛線是它往外的連線。)

圖上有三件事要看。

  • 它不在任何一條資料流上。 封包、事件、決策三條線(總覽那一篇的三條資料流)都不經過它。它是從旁邊接上 Docker 引擎的一個操作台,安裝腳本自己管容器時用的是 docker compose 指令,不經過它。
  • 它與 Docker 引擎之間那條線,權限比管理者的 SSH 還大。 Docker 的 socket 等於主機的 root:能透過它建立一個把主機根目錄掛進來的容器。Portainer 掛著這條線,所以能登入 Portainer 的人,就有這個能力。第五節會講這條線能做到什麼。
  • 它會往外連。 登入後首頁有「Latest News From Portainer」一段來自原廠的公告,是它定期抓的;有新版時會多一行「New version available」,是它連回原廠查的;它還會從 GitHub 載入應用程式範本。這是三個管理介面裡往外連最多的一個。

三、登入之後看到什麼

在 --admin-ips 列出的電腦上開 https://192.168.0.112:9443/,瀏覽器會警告憑證不受信任,選「進階」再「繼續前往」。帳號 admin,密碼取自主機 B:

# 主機 B
sudo grep '^PORTAINER_ADMIN_PASSWORD=' /opt/integrated-waf/.env

登入後第一頁是 Home,有一張名為 local 的環境卡片。Portainer 把每一個它管的 Docker 叫做一個環境(environment),出廠的環境清單其實是空的,連它自己所在的這台 Docker 也不在裡面,首頁只會寫 No environment available for management,要開過一次精靈頁(#!/wizard)它才會登記。安裝腳本在 Portainer 起來之後用它的 API 替讀者做掉了這一步,只在清單是空的時候做,之後存在它的資料庫裡,重啟不用再做。

卡片上的內容是從 Docker 引擎拿回來的摘要:

local   Up   Standalone 29.1.3   unix:///var/run/docker.sock
12 of 12 containers running   1 NODES   4 CORES   6.2 GB MEMORY

12 個容器就是本安裝包的全部:WAF 兩個(主站與歡迎頁)、Suricata、CrowdSec、Vector、ClickHouse、od-bridge、cloudflared、歡迎頁的靜態伺服器,加上 Grafana、EveBox、Portainer 自己。點進去是 Dashboard:1 個 stack(compose 檔定義的那一組,名字是 secstack)、12 個容器、14 個映像、21 個資料卷、4 個網路;左側是 Containers、Images、Networks、Volumes 等項目。Containers 頁一列一個容器,有狀態、映像、建立時間、IP 與埠,每一列可以看 Logs、看 Stats、開 Console 進到容器裡。這幾頁的內容就是 docker compose ps、docker compose logs、docker compose exec 這三個指令的畫面版。本系列其他篇裡每一個「主機 B」開頭的指令,都可以在這裡用滑鼠做到;反過來說,沒有 Portainer,那些指令也都還在。

四、舊版為什麼點進去是「環境無法連線」,換版之後會發生什麼

先講舊版。2026 年 10 月 9 日之前的安裝包內建 2.21.4,自己開精靈頁登記好 local 之後,點它的卡片,畫面回到 Home,右上角跳出:

Failed loading environment
The environment named local is unreachable.

卡片上的狀態也從 Up 變成 Down。但 Docker 明明在跑,它剛剛還拿到了容器數量。按 F12 看網路請求,點進環境時它發了這一個:

GET /api/endpoints/2/docker/v1.41/_ping     → 400
{"message":"client version 1.41 is too old. Minimum supported API version is 1.44,
 please upgrade your client to a newer version"}

Portainer 的前端用 Docker API 的 1.41 版跟引擎打招呼。Ubuntu 24.04 目前套件庫裡的 Docker 是 29.1.3,這個版本把最低支援的 API 版本提高到 1.44,1.41 被拒絕。一被拒絕,Portainer 就把這個環境標成 Down,之後所有的操作頁面都進不去。摘要還拿得到,是因為摘要走的是另一條沒有指定版本的路。

所以這不是防火牆、不是 socket 權限、不是密碼,而是當時安裝包內建的 Portainer 版本太舊、讀者的 Ubuntu 又夠新。兩年前這個版本發布時 Docker 的最低 API 版本還是 1.24,當時不會有這個問題;之後 Ubuntu 24.04 的 docker.io 套件升到了 29,問題就出現了。確認你的主機 B 是不是這種組合:

# 主機 B
docker version --format '{{.Server.Version}} api={{.Server.APIVersion}} min={{.Server.MinAPIVersion}}'
29.1.3 api=1.52 min=1.44

min 大於 1.41 就是這個情況。解法是換新版的 Portainer,安裝包從 2026 年 10 月 9 日起改用社群版 2.45.2(本文寫作時的最新長期支援版)。新裝的讀者直接拿到新版,環境登記後狀態一直是 Up,容器清單正常列出,第三節看到的就是它。已經裝過、用 install.sh --update 升上來的讀者,有三件事會發生:

  • 它自己的資料庫會升級。 新版第一次啟動時先把舊資料庫備份到資料卷的 backups/portainer.db.bak,再一路從 2.21.4 升到 2.45.2,紀錄裡是一連串 migrating data to 2.22.0 … 2.45.0,最後一行 db migrated to 2.45.2。帳號與密碼不變,用原本的密碼登入即可(紀錄裡 instance already has an administrator user defined)。
  • 本機環境會被登記。 升級時環境清單若還是空的,安裝腳本會登記 local;舊版時自己開精靈頁登記過的,安裝腳本不動它。舊版留下的那個環境在新版會自己變回 Up,不必刪掉重建。
  • 設定頁少了一個選項。 舊版設定裡有「使用統計回報」(API 裡的 EnableTelemetry),安裝包把它關著;2.45 的設定頁與 API 都沒有這一項了,往外連的只剩查新版、抓公告、載範本三種。

五、那條線能做什麼

Portainer 掛著 /var/run/docker.sock。這條線的意義要講清楚,因為它決定了這個容器該放在誰的手上。

Docker 引擎以 root 執行,透過 socket 收到的指令都以 root 的身分做。能對 socket 說話的人,可以要求引擎建立一個新容器、把主機的 / 掛進去、以 root 跑一個 shell,接著就能讀寫主機上的任何檔案,包括 .env 裡所有的密碼、Suricata 的規則、nftables 的設定,以及其他容器的資料卷。這不是 Portainer 的漏洞,而是 Docker 的設計:socket 的存取權本來就等於主機的 root,主機上的 docker 群組就是為此而存在的。Portainer 只是把這條線接到了一個網頁登入畫面後面。

所以評估它的時候要用的尺是這把:

項目 說明
誰能登入 Portainer 就是誰能當主機 B 的 root。出廠只有 admin 一個帳號、一組密碼,在 .env 裡是明文
誰能連 9443 埠 --admin-ips 名單。名單上任何一台電腦被拿下,拿下的人只差一組密碼就到 root
密碼在哪些地方 安裝結尾的畫面、.env、它自己的資料庫(雜湊過)。安裝時印出來的那一份,不要留在可以被翻到的地方
連線是否加密 是,9443 是 HTTPS。但憑證自簽,瀏覽器每次都要按「繼續前往」,久了會養成對憑證警告視而不見的習慣,這在其他網站上是危險的
登入的有效期 8 小時。重啟 Portainer 容器會讓所有已登入的瀏覽器回到登入頁,實測如此
它自己的資料庫 沒有加密。啟動紀錄裡寫 encryption key file not present、proceeding without encryption key。但能讀到這個資料卷的人本來就已經是 root 了,這一項不改變什麼

Grafana 那一篇說「能登入 Grafana 的人拿到的是 ClickHouse 的管理權」,Portainer 的版本是「能登入 Portainer 的人拿到的是整台主機」。三個管理介面裡它最需要被關掉:不打算用圖形介面管容器的節點,安裝時加 --no-ui,三個一起不裝;只想留 Grafana 的,裝完後把 Portainer 這一個容器停掉。

六、它不做的事

限制 說明
與防禦無關 不看事件、不擋攻擊、不參與建案與處置。主機 B 上沒有任何元件呼叫它
舊版(2.21.4)進不了環境 第四節。安裝包已換 2.45.2;用 --update 升上來的資料庫會自動升級
Portainer 出廠沒登記環境 安裝腳本用它的 API 登記本機 Docker 為 local。這個動作只做一次,存在資料卷裡
看不到主機 A 主機 A 不是容器,Portainer 管不到;主機 A 也不會連它
不管主機本身 nftables、cron 的輪替排程、網卡卸載的設定都在容器外,它看不到
一個帳號 要分人,得自己在 Users 裡建。社群版沒有「只能看不能動」這種細緻的角色,每個使用者對它管的環境不是全有就是全無
會自己往外連 查新版、抓公告、載範本,三種都沒有關。舊版還有一項使用統計回報(EnableTelemetry),安裝包關著;2.45 已沒有這個選項
不會自己更新 版本跟著安裝包走。有新版時首頁那行「New version available」只是提醒,按了也不會更新

把它停掉會怎樣,實測過一次:停止 Portainer 容器 22 秒。這段期間 9443 埠連不上;對 WAF 送的攻擊請求照常回 403,EveBox 照常回應,其他 11 個容器沒有任何變化。重新啟動後 2 秒就能登入,環境清單與帳號都在。它是整個安裝包裡停掉之後影響最小的一個。

七、怎麼確認它在做事

先看它活著沒有。這個端點不必登入,憑證自簽所以要加 -k:

# 主機 B
curl -sk https://127.0.0.1:9443/api/system/status
{"Version":"2.45.2","InstanceID":"9c69ca7c-0d33-4ab3-99c5-755aa6c84762"}

再看環境登記好了沒、連不連得上。這一個要登入,拿 .env 裡的密碼換一個 token,再用 token 問:

# 主機 B
PW=$(sudo grep '^PORTAINER_ADMIN_PASSWORD=' /opt/integrated-waf/.env | cut -d= -f2-)
TOKEN=$(curl -sk -X POST https://127.0.0.1:9443/api/auth -H 'Content-Type: application/json' \
  -d "{\"username\":\"admin\",\"password\":\"$PW\"}" | python3 -c 'import sys,json; print(json.load(sys.stdin)["jwt"])')
curl -sk https://127.0.0.1:9443/api/endpoints -H "Authorization: Bearer $TOKEN" | python3 -c '
import sys,json
for e in json.load(sys.stdin): print(e["Id"], e["Name"], e["URL"], "Status", e["Status"])'
3 local unix:///var/run/docker.sock Status 1

沒有任何一列,就是安裝腳本登記失敗(安裝結尾會有一行警告),開一次精靈頁即可。Status 1 是 Up,2 是 Down;舊版配 Docker 29 的話,只要在畫面上點過一次環境,這裡就會變成 2,新版一直是 1。

最後,它管得到的東西,不用它也看得到。本系列其他篇用的都是這三個指令,它們不依賴 Portainer:

# 主機 B
cd /opt/integrated-waf
sudo docker compose ps --format 'table {{.Name}}\t{{.Status}}'
NAME                     STATUS
secstack-clickhouse-1    Up 35 hours (healthy)
secstack-cloudflared-1   Up 35 hours
secstack-crowdsec-1      Up 35 hours
secstack-evebox-1        Up 35 hours
secstack-grafana-1       Up 35 hours
secstack-od-bridge-1     Up 35 hours
secstack-portainer-1     Up 35 hours
secstack-suricata-1      Up 35 hours
secstack-vector-1        Up 35 hours
secstack-waf-nginx-1     Up 35 hours (healthy)
secstack-waf-welcome-1   Up 35 hours (healthy)
secstack-welcome-1       Up 35 hours

sudo docker compose logs --tail 20 od-bridge      # 看某個容器的紀錄
sudo docker compose exec -T clickhouse clickhouse-client --query 'SELECT 1'   # 進某個容器下指令

Portainer 能做的就是這三件事的畫面版。它在整體裡的位置到此說完:不在任何一條線上,誰都不需要它,但它握著整台主機的鑰匙。要不要留它,看的不是功能,是誰會拿到那把鑰匙。


上一篇
EveBox:翻 Suricata 每一行紀錄的窗口
下一篇
Vector:三種告警變成一種事件
系列文
一鍵完成六套開源防禦系統整合 共 28 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言